using System;
using System.Collections.Generic;
using System.Text;
using SurveyHost.Core.DAL;
using SubSonic;
using System.Web;

namespace SurveyHost.Core
{
    public static class StatusHelper
    {
        /// <summary>
        /// Checks to see if a user has consented to the survey terms.
        /// Does not mean the user is valid; a valid user must have passed participant validation.
        /// </summary>
        /// <param name="userId">The user id to search for</param>
        /// <returns>True if consent has been recorded, false otherwise.</returns>
        public static bool HasUserConsented(Guid userId)
        {
            int count = UserStatus.Query()
                .WHERE(UserStatus.Columns.UserId, userId)
                .AND(UserStatus.Columns.EnteredName,Comparison.IsNot,null)
                .GetCount(UserStatus.Columns.UserId);
            if (count == 0) return false;
            return true;
        }

        /// <summary>
        /// Checks to see if the current user has already filled out the consent form.
        /// </summary>
        /// <returns>True if consented, false otherwise.</returns>
        public static bool CurrentUserHasConsented()
        {
            return HasUserConsented(WebUtil.CurrentUserId());
        }

        public static bool UserIsAdmin()
        {
            if (HttpContext.Current == null || HttpContext.Current.User == null)
                return false;
            return HttpContext.Current.User.IsInRole("Admin");            
        }

        /// <summary>
        /// Records a user's consent in the database
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <param name="userName">Name of the user (must be included to indicate consent).</param>
        /// <returns>Number of affected rows</returns>
        public static void Consent(Guid userId, string userName)
        {
            if (string.IsNullOrEmpty(userName))
                throw new ArgumentException("userName");
            UserStatus stat = new UserStatus();
            stat.UserId = userId;
            stat.EnteredName = userName;
            stat.ConsentDate = DateTime.Now;
            stat.Save();
        }

        /// <summary>
        /// Marks a user has having completed the survey
        /// </summary>
        /// <param name="userId">The user to update</param>
        /// <returns>The number of affected rows</returns>
        public static void MarkCompleted(Guid userId)
        {
            UserStatus stat = ActiveRecord<UserStatus>.FetchByID(userId);
            if (stat == null || stat.UserId != userId)
                throw new InvalidOperationException("User has not consented.  Cannot save data.");
            stat.Completed = true;
            stat.Save();
        }

        /// <summary>
        /// Determines if a given user has completed
        /// </summary>
        /// <param name="userId">The UserId of the user to check</param>
        /// <returns><c>true</c> if the user has completed the survey, <c>false</c> otherwise.</returns>
        public static bool IsCompleted(Guid userId)
        {
            UserStatus stat = UserStatus.FetchByID(userId);
            if (stat == null || stat.UserId != userId)
                return false;
            return stat.Completed;
        }

        public static void SetValidationStatus(Guid userId, bool isAtLeast18, bool hasBeenInARelationship)
        {
            UserStatus stat = UserStatus.FetchByID(userId);
            if (stat == null || stat.UserId != userId)
                throw new InvalidOperationException("User has not consented.  Cannot save data.");
            stat.AreOrOver18 = isAtLeast18;
            stat.RelationshipInPastYear = hasBeenInARelationship;
            stat.ValidationComplete = true;
            stat.Save();
            //HACK:  marking invalid people as completed.
            if (isAtLeast18 && hasBeenInARelationship) return;
            StatusHelper.MarkCompleted(userId);
        }

        /// <summary>
        /// Indicates a user has submitted to the terms and conditions of the survey and meets eligability 
        /// </summary>
        /// <param name="userId">The user ID</param>
        /// <returns></returns>
        public static bool UserIsValid(Guid userId)
        {
            UserStatus stat = ActiveRecord<UserStatus>.FetchByID(userId);
            if (stat == null || stat.UserId != userId)
                return false;
            if (string.IsNullOrEmpty(stat.EnteredName))
                return false;
            return stat.AreOrOver18 && stat.RelationshipInPastYear && stat.ValidationComplete;
        }

        /// <summary>
        /// Users the has completed validation.  This method does not determine if a user is able to take the survey, just that the user has completed validation.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        public static bool UserHasCompletedValidation(Guid userId)
        {
            UserStatus stat = UserStatus.FetchByID(userId);
            if (stat == null || stat.UserId != userId)
                return false;
            if (string.IsNullOrEmpty(stat.EnteredName))
                return false;
            return stat.ValidationComplete;        
        }
    }
}
